package com.example.malllocationserver.utils;

import java.util.*;

import static java.lang.Math.*;

public class operation {
    public operation(){

    }
    //根据Wifi指纹获取相似度
    public int[] distance_wifi(Map<String , Integer> target , Map<String , Integer> node){
        List<String> target_name = new ArrayList<>(target.keySet());
        List<String> node_name = new ArrayList<>(node.keySet());
        int distance = 0;
        int count = 0;
        for(String _name : target_name){
            for(String name_ : node_name){
                if (Objects.equals(name_, _name)){
                    //利用曼哈顿距离计算距离
                    distance += abs(node.get(_name) - target.get(_name));
                    count ++;
                }
            }
        }
        //返回距离和相同的wifi个数
        return new int[]{distance, count};
    }

    public double distance_gm(double[] gm, double[] target){
        int n = target.length;
        double fz = 0 ,fmg = 0 , fmt = 0;

        //余弦相似度
//        for(int i = 0;i<n;i++){
//            fz += gm[i]*target[i];
//            fmg += pow(gm[i],2);
//            fmt += pow(target[i],2);
//        }
//
//        double distance = fz/(sqrt(fmg)+sqrt(fmt));


        //欧氏距离
        double distance = 0;
        for(int i=1;i<3;i++){
            distance += pow(gm[i]-target[i],2);
        }

        //伪余弦值表示
//        double distance = 0;
//        double cosine_tar = cosine(target[1] , target[2]);
//        double cosine_gm = cosine(gm[1],gm[2]);
//        distance = abs(cosine_tar - cosine_gm);
        return distance;
    }

    //    计算世界坐标的距离
    public double distance_gb(double[] target , double[] db){
        double distance = 0;
        for(int i=0;i<3;i++){
            distance += pow(db[i]-target[i],2);
        }

        return distance;
    }

    public double cosine(double x , double y){
        double cosine = 0;
        cosine = x*y/(sqrt(pow(x,2)+pow(y,2)));
        return cosine;
    }

    public String knn_load(int n ,Map<String , double[]> data , double[] target){
        Map<Double,String> distance_list = new HashMap<>();
        List<String> nameList = new ArrayList<>(data.keySet());
        for(String name : nameList){
            double distance = distance_gb(target , data.get(name));
            distance_list.put(distance,name);
        }
        List<Double> distance_ = new ArrayList<>(distance_list.keySet());
        Collections.sort(distance_);
        List<Double> distances = new ArrayList<>();
        for(int i=0;i<5;i++)
            distances.add(distance_.get(distance_.size()-i-1));

        Map<String,Integer> name_count = new HashMap<>();
        for(Double distance : distances){
            String name = distance_list.get(distance);
            if(name_count.containsKey(name))
                name_count.put(name,name_count.get(name)+1);
            else
                name_count.put(name,1);
        }
        String ans = null;
        List<String> count_name = new ArrayList<>(name_count.keySet());
        int max = 0;
        for(String name : count_name){
            if(name_count.get(name)>=max){
                ans = name;
                max = name_count.get(name);
            }
        }

        return ans;
    }

    public String knn_wifi(List<Map<String,Integer>>Wifi,Map<String , Integer> target,List<String> Type,int k){
        int distance = 0;
        int count = 0;
        //定义最小的匹配数目
        int min = 100000;

        //用来存储距离和名字
        Map<Integer , String> name_count = new HashMap<>();
        String _type = null;
        int n = Wifi.size();
        for(int i=0;i<n;i++){
            count = distance_wifi(Wifi.get(i) , target)[1];
            distance = distance_wifi(Wifi.get(i) , target)[0]+100*(11-count);
            _type = Type.get(i);
            name_count.put(distance,_type);

        }
        List<Integer> _distance = new ArrayList<>(name_count.keySet());
        Collections.sort(_distance);
        List<String> names = new ArrayList<>();

        //排序之后获得排名前5的名字
        for(int i=0;i<5;i++){
            names.add(name_count.get(_distance.get(i)));
        }

        Map<String,Integer> Count = new HashMap<>();

        //记录前五的名字中出现频率最高的Type
        for(String _name : names){
            if(!Count.containsKey(_name))
                Count.put(_name , 1);
            else{
                int i =Count.get(_name);
                Count.put(_name , i+1);
            }
        }
        List<Integer> distance_ = new ArrayList<>(Count.values());
        Collections.sort(distance_);
        int m = distance_.get(distance_.size()-1);
        for(String _name : names){
            if(Count.get(_name) == m)
                return _name;
        }
        return null;
    }
    public String nn_load(Map<String,double[]> data,double[] target){
        double min = 1000000;
        String ans = null;
        List<String> name = new ArrayList<>(data.keySet());
        for(String _name : name){
            double distance = distance_gb(data.get(_name),target);
            if(distance <= min){
                min = distance;
                ans = _name;
            }
        }
        return ans;
    }
}
